﻿// Inner Fire 游戏引擎库
// DxLights 渲染器光源功能
//
// Copyright (c) 2025 by 尔西大帝. All rights reserved.
//
// 用于DirectX的渲染器。
// 此文件分装用于光源功能
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2025-04-23

#include "dx_lights.h"
#include "dx_graphics.h"
#include <game/core/timer.h>
#include <kfile.h>

namespace ifire::dx {
ifire::dx::DxLights::DxLights(DxGraphics* dx) : DxModule(dx) {}

void DxLights::RotateLights() {
  // 是否旋转光源
  static bool ROTATE_LIGHT = dx_->Config()("RotateLight");

  //
  // 调整一个旋转光源
  //
  if (ROTATE_LIGHT) {
    static float light_angle = 0.0f;
    static auto base_dir = dx_->GetMainPass().lights[0].direction;
    light_angle += 1.0f * game::g_timer.fixedDeltaTime;

    XMMATRIX R = XMMatrixRotationY(light_angle);
    XMVECTOR lightDir = XMLoadFloat3(&base_dir);
    lightDir = XMVector3TransformNormal(lightDir, R);
    XMStoreFloat3(&dx_->GetMainPass().lights[0].direction, lightDir);
  }
}

static std::string LIGHT_SETTINGS = "settings/lights.xml";
static time_t last_light_write_time = 0;

void DxLights::UpdateLights() {
  auto change_time = ikit::get_file_changed(LIGHT_SETTINGS.c_str());
  if (change_time == last_light_write_time) {
    return;
  }
  // 重置时间
  last_light_write_time = change_time;

  // 载入光源
  auto lights = ikit::Xml_ReadItems<LightSetting>(LIGHT_SETTINGS, "Light");
  // 计算项目
  int directional_count = 0;
  int point_count = 0;
  int spot_count = 0;
  int index = 0;
  for (int i = 0; i < lights.size(); i++) {
    if (lights[i].disable) { // 跳过不使用的
      continue;
    }
    if (lights[i].type == LightType::Directional) {
      directional_count += 1;
    } else if (lights[i].type == LightType::Point) {
      point_count += 1;
    } else if (lights[i].type == LightType::Spot) {
      spot_count += 1;
    }

    // 将光源填充到Pass中
    // 注意这里有一个BUG，就是光源必须按顺序配置。先平行光，再点光，再聚光灯
    // 因为也只是调试，所以暂时不用解决这个问题。
    dx_->GetMainPass().lights[index] = lights[i].light;
    index++;
  }

  // 设置每个光源的量
  /*main_pass_.directional_light_count = directional_count;
  main_pass_.point_light_count = point_count;
  main_pass_.spot_light_count = spot_count;*/
}

} // namespace ifire::dx